#include "stream.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

struct Stream * createStream()
{
	struct Stream * stream = malloc(sizeof(struct Stream));
	stream->size = 0;
	stream->data = 0;
	return stream;
}

void destroyStream(struct Stream * stream)
{
	if(stream)
	{
		if(stream->data)
		{
			free(stream->data);
		}
		free(stream);
	}
}

void push_back(struct Stream * stream, size_t size, unsigned char * data)
{
	if(stream)
	{
		if(size > 0)
		{
			if(stream->data)
			{
				unsigned char * temp = stream->data;
				stream->data = malloc(stream->size + size);
				memcpy(stream->data, temp, stream->size);
				memcpy(stream->data + stream->size, data, size);
				free(temp);
				
				stream->size += size;
			}
			else
			{
				stream->data = malloc(size);
				memcpy(stream->data, data, size);
				stream->size = size;
			}
		}
	}
	else
	{
		printf("push_back() received null pointer for stream.\n");
	}
}

void pop_front(struct Stream * stream, size_t size)
{
	if(stream)
	{
		if(size > 0)
		{
			if(size >= stream->size)
			{
				stream->size = 0;
				if(stream->data)
				{
					free(stream->data);
					stream->data = 0;
				}
			}
			else
			{
				stream->size -= size;
				
				unsigned char * temp = stream->data;
				stream->data = malloc(stream->size);
				memcpy(stream->data, temp + size, stream->size);
				free(temp);
			}
		}
	}
	else
	{
		printf("pop_front() received null pointer for stream.\n");
	}
}

void stream_unit_test()
{
	unsigned char abc[3] = {'a', 'b', 'c'};
	unsigned char def[3] = {'d', 'e', 'f'};
	
	struct Stream * stream = createStream();
	push_back(stream, 3, abc);
	push_back(stream, 3, def);
	pop_front(stream, 2);
	if(stream->data[0] != 'c')
	{
		printf("Stream Unit Test Failed 00");
		return;
	}
	if(stream->size != 4)
	{
		printf("Stream Unit Test Failed 01");
		return;
	}
	pop_front(stream, 2);
	if(stream->data[0] != 'e')
	{
		printf("Stream Unit Test Failed 02");
		return;
	}
	if(stream->size != 2)
	{
		printf("Stream Unit Test Failed 03");
		return;
	}
	pop_front(stream, 2);
	if(stream->size != 0)
	{
		printf("Stream Unit Test Failed 04");
		return;
	}
	destroyStream(stream);
	printf("Stream Unit Test OK\n");
}
